Õppige Reacti useTransition haaki, et kõrvaldada blokeerivad renderdused ja luua sujuvad, suure jõudlusega kasutajaliidesed. Saage teada isPending, startTransition ja samaaegsete funktsioonide kohta globaalsele vaatajaskonnale.
React useTransition: SĂĽvauurimine mitteblokeerivatesse kasutajaliidese uuendustesse globaalsete rakenduste jaoks
Kaasaegse veebiarenduse maailmas on kasutajakogemus (UX) ülimalt tähtis. Globaalse vaatajaskonna jaoks tähendab see rakenduste loomist, mis tunduvad kiired, reageerivad ja intuitiivsed, olenemata kasutaja seadmest või võrgutingimustest. Üks levinumaid pettumusi, millega kasutajad kokku puutuvad, on külmunud või loid liides – rakendus, mis lõpetab ülesandega tegeledes reageerimise. Selle põhjuseks on sageli Reacti "blokeerivad renderdused".
React 18 tutvustas võimsat tööriistakomplekti selle probleemi lahendamiseks, juhatades sisse samaaegse Reacti ajastu. Selle uue paradigma südames on üllatavalt lihtne, kuid transformatiivne haak: useTransition. See haak annab arendajatele peenhäälestatud kontrolli renderdamisprotsessi üle, võimaldades meil ehitada keerukaid, andmerikkaid rakendusi, mis ei kaota kunagi oma sujuvust.
See põhjalik juhend viib teid süvitsi useTransition-i. Uurime probleemi, mida see lahendab, selle peamist mehaanikat, praktilisi rakendusmustreid ja täiustatud kasutusjuhtumeid. Lõpuks olete valmis seda haaki kasutama, et ehitada maailmatasemel mitteblokeerivaid kasutajaliideseid.
Probleem: Blokeeriva renderduse tĂĽrannia
Enne kui me lahendust hinnata saame, peame probleemist täielikult aru saama. Mis täpselt on blokeeriv renderdus?
Traditsioonilises Reactis koheldakse iga olekuvärskendust sama kõrge prioriteediga. Kui te kutsute setState-i, alustab React protsessi komponendi ja selle laste uuesti renderdamiseks. Kui see uuesti renderdamine on arvutuslikult kallis – näiteks tuhandete üksuste loendi filtreerimine või keeruka andmete visualiseerimise värskendamine –, muutub brauseri põhivoog hõivatuks. Kui see töö on käimas, ei saa brauser midagi muud teha. See ei saa reageerida kasutaja sisendile, nagu klõpsud, tippimine või kerimine. Kogu leht külmub.
Reaalmaailma stsenaarium: Aeglane otsinguväli
Kujutage ette, et ehitate e-kaubanduse platvormi globaalsele turule. Teil on otsinguleht sisestusväljaga ja selle all kuvatakse 10 000 toote loend. Kui kasutaja sisestab otsinguväljale midagi, värskendate oleku muutuja, mis seejärel filtreerib massiivse toodete loendi.
Siin on kasutaja kogemus ilma useTransition-ita:
- Kasutaja sisestab tähe 'S'.
- React käivitab kohe uuesti renderduse, et filtreerida 10 000 toodet.
- See filtreerimis- ja renderdamisprotsess võtab aega näiteks 300 millisekundit.
- Nende 300 ms jooksul on kogu UI külmunud. Kasutaja sisestatud 'S' ei pruugi isegi sisestuskasti ilmuda enne, kui renderdus on lõpule viidud.
- Kasutaja, kiire trükkija, sisestab seejärel 'h', 'o', 'e', 's'. Iga klahvivajutus käivitab veel ühe kalli blokeeriva renderduse, muutes sisestuse reageerimatuks ja masendavaks.
See halb kogemus võib viia kasutajate loobumiseni ja negatiivse arusaamani teie rakenduse kvaliteedist. See on kriitiline jõudluse kitsaskoht, eriti rakenduste puhul, mis peavad hakkama saama suurte andmekogumitega.
Tutvustame `useTransition`-i: Prioriseerimise põhimõte
Samaaegse Reacti põhiidee on see, et mitte kõik värskendused pole võrdselt pakilised. Teksti sisestuse värskendus, kus kasutaja ootab, et tema tähed ilmuksid kohe, on kõrge prioriteediga värskendus. Kuid filtreeritud tulemuste loendi värskendus on vähem kiireloomuline; kasutaja talub kerget viivitust seni, kuni peamine liides jääb interaktiivseks.
See on täpselt see, kus useTransition sisse tuleb. See võimaldab teil märkida teatud olekuvärskendused "üleminekuteks" – madala prioriteediga mitteblokeerivad värskendused, mida saab katkestada, kui tuleb pakilisem värskendus.
Kasutades analoogiat, mõelge oma rakenduse värskendustele kui ülesannetele ühele väga hõivatud assistendile (brauseri põhivoog). Ilma useTransition-ita võtab assistent iga ülesande vastu ja töötab sellega, kuni see on valmis, ignoreerides kõike muud. Koos useTransition-iga saate assistendile öelda: "See ülesanne on oluline, aga sa võid sellega tegeleda oma vabal ajal. Kui ma annan sulle pakilisema ülesande, jäta see maha ja tegele esmalt uuega."
useTransition haak tagastab massiivi kahe elemendiga:
isPending: Boole'i väärtus, mis ontrue, kui üleminek on aktiivne (st madala prioriteediga renderdus on pooleli).startTransition: Funktsioon, millesse te madala prioriteediga olekuvärskenduse mässite.
import { useTransition } from 'react';
function MyComponent() {
const [isPending, startTransition] = useTransition();
// ...
}
Mässides olekuvärskenduse startTransition-isse, ütlete Reactile: "See värskendus võib olla aeglane. Palun ärge blokeerige UI-d selle töötlemise ajal. Võite seda renderdama hakata, aga kui kasutaja midagi muud teeb, seadke tema tegevus prioriteediks."
Kuidas `useTransition`-i kasutada: Praktiline juhend
Refaktoreerime oma aeglase otsinguvälja näidet, et näha useTransition-i töös. Eesmärk on hoida otsingu sisestus reageerivana, samal ajal kui toodete loend uueneb taustal.
1. samm: Oleku seadistamine
Meil on vaja kahte olekut: üks kasutaja sisendi jaoks (kõrge prioriteediga) ja üks filtreeritud otsingupäringu jaoks (madala prioriteediga).
import { useState, useTransition } from 'react';
// Eeldame, et see on suur toodete loend
const allProducts = generateProducts();
function ProductSearch() {
const [isPending, startTransition] = useTransition();
const [inputValue, setInputValue] = useState('');
const [searchQuery, setSearchQuery] = useState('');
// ...
}
2. samm: Kõrge prioriteediga värskenduse rakendamine
Kasutaja sisend tekstiväljal peaks olema kohene. Värskendame inputValue olekut otse onChange käitlejas. See on kõrge prioriteediga värskendus, sest kasutaja peab nägema, mida ta kohe kirjutab.
const handleInputChange = (e) => {
setInputValue(e.target.value);
// ...
};
3. samm: Madala prioriteediga värskenduse mässimine `startTransition`-isse
Kallis osa on `searchQuery` värskendamine, mis käivitab suure toodete loendi filtreerimise. See on värskendus, mida me tahame üleminekuks märkida.
const handleInputChange = (e) => {
// Kõrge prioriteediga värskendus: hoiab sisestusvälja reageerivana
setInputValue(e.target.value);
// Madala prioriteediga värskendus: mässitud startTransition-isse
startTransition(() => {
setSearchQuery(e.target.value);
});
};
Mis nĂĽĂĽd juhtub, kui kasutaja midagi kirjutab?
- Kasutaja kirjutab tähe.
- Kutsutakse
setInputValue. React kohtleb seda kui pakilist värskendust ja renderdab kohe sisestusvälja uue tähega uuesti. UI ei ole blokeeritud. - Kutsutakse
startTransition. React hakkab uut komponendipuu ette valmistama värskendatudsearchQuery-ga taustal. - Kui kasutaja kirjutab enne ülemineku lõppu veel ühe tähe, loobub React vanast taustrenderdusest ja alustab uut renderdust uusima väärtusega.
Tulemuseks on täiesti sujuv sisestusväli. Kasutaja saab kirjutada nii kiiresti kui ta tahab ja UI ei külmu kunagi. Toodete loend uueneb uusima otsingupäringuga niipea, kui Reactil on aega renderdus lõpetada.
4. samm: `isPending` oleku kasutamine kasutaja tagasiside jaoks
Kuigi toodete loend uueneb taustal, võib UI näidata aegunud andmeid. See on suurepärane võimalus kasutada isPending boole'i, et anda kasutajale visuaalset tagasisidet, et midagi toimub.
Me saame seda kasutada, et näidata laadimiskursorit või vähendada loendi läbipaistmatust, mis näitab, et sisu uuendatakse.
function ProductSearch() {
const [isPending, startTransition] = useTransition();
const [inputValue, setInputValue] = useState('');
const [searchQuery, setSearchQuery] = useState('');
const handleInputChange = (e) => {
setInputValue(e.target.value);
startTransition(() => {
setSearchQuery(e.target.value);
});
};
const filteredProducts = allProducts.filter(p =>
p.name.toLowerCase().includes(searchQuery.toLowerCase())
);
return (
<div>
<h2>Globaalne tooteotsing</h2>
<input
type="text"
value={inputValue}
onChange={handleInputChange}
placeholder="Otsi tooteid..."
/>
{isPending && <p>Loendi uuendamine...</p>}
<div style={{ opacity: isPending ? 0.5 : 1 }}>
<ProductList products={filteredProducts} />
</div>
</div>
);
}
Nüüd, kui startTransition töötleb aeglast renderdust, muutub isPending lipp true-ks. See käivitab kohe kiire, kõrge prioriteediga renderduse, et näidata sõnumit "Loendi uuendamine..." ja hämardada toodete loendit. See annab kohest tagasisidet, parandades oluliselt rakenduse tajutavat jõudlust.
Üleminekud vs. drossel ja põrke vähendamine: Oluline erinevus
Jõudluse optimeerimisega kursis olevad arendajad võivad imestada: "Kuidas see erineb põrke vähendamisest või drosselist?" See on kriitiline segaduse punkt, mida tasub selgitada.
- Põrke vähendamine ja drossel on tehnikad, et kontrollida funktsiooni täitmise kiirust. Põrke vähendamine ootab enne käivitamist sündmustes pausi, samas kui drossel tagab, et funktsiooni kutsutakse maksimaalselt üks kord määratud ajavahemiku jooksul. Need on üldised JavaScripti mustrid, mis viskavad vahepealsed sündmused ära. Kui kasutaja kirjutab kiiresti "shoes", võib põrke vähendamisega käitleja käivitada ainult ühe sündmuse lõpliku väärtuse "shoes" jaoks.
- `useTransition` on React-spetsiifiline funktsioon, mis kontrollib renderdamise prioriteeti. See ei viska sündmusi ära. See ütleb Reactile, et ta prooviks renderdada iga olekuvärskendust, mis on edastatud `startTransition`-ile, aga et ta teeks seda ilma UI-d blokeerimata. Kui juhtub kõrgema prioriteediga värskendus (nagu teine klahvivajutus), katkestab React poolelioleva ülemineku, et esmalt tegeleda kiireloomulise värskendusega. See muudab selle põhimõtteliselt rohkem integreerituks Reacti renderdamise elutsükliga ja pakub üldiselt paremat kasutajakogemust, kuna UI jääb kogu ulatuses interaktiivseks.
Lühidalt: põrke vähendamine on sündmuste ignoreerimine; `useTransition` on renderduste poolt mitte blokeeritud olemine.
Täiustatud kasutusjuhtumid globaalsel skaalal
`useTransition`-i võimsus ulatub kaugemale lihtsatest otsingusisenditest. See on põhiline tööriist iga keeruka, interaktiivse UI jaoks.
1. Keerukas, rahvusvaheline e-kaubanduse filtreerimine
Kujutage ette keerukat filtreerimisribat e-kaubanduse saidil, mis teenindab kliente üle maailma. Kasutajad saavad filtreerida hinnavahemiku (kohalikus valuutas), brändi, kategooria, tarnekoha ja toote hinnangu järgi. Iga muudatus filtri juhtimisseadmes (märkeruut, liugur) võib käivitada tootevõre kalli uuesti renderdamise.
Mässides nende filtrite olekuvärskendused `startTransition`-isse, saate tagada, et ribamenüü juhtnupud jäävad erksaks ja reageerivaks. Kasutaja saab kiiresti klõpsata mitmel märkeruudul ilma, et UI pärast iga klõpsu külmuks. Toodete võre uueneb taustal, kusjuures isPending olek annab selge tagasiside.
2. Interaktiivne andmete visualiseerimine ja armatuurlauad
Kaaluge äriteabe armatuurlauda, mis kuvab globaalseid müügiandmeid kaardil ja mitmel graafikul. Kasutaja võib muuta kuupäevavahemikku "Viimased 30 päeva" väärtuseks "Viimane aasta". See võib hõlmata tohutu hulga andmete töötlemist, et visualiseeringud uuesti arvutada ja uuesti renderdada.
Ilma useTransition-ita külmutaks kuupäevavahemiku muutmine kogu armatuurlaua. Koos useTransition-iga jääb kuupäevavahemiku valija interaktiivseks ja vanad graafikud võivad jääda nähtavaks (võib-olla hämardatud), samal ajal kui uusi andmeid töödeldakse ja renderdatakse taustal. See loob palju professionaalsema ja sujuvama kogemuse.
3. `useTransition`-i ja `Suspense`-i kombineerimine andmete toomiseks
Samaaegse Reacti tõeline jõud vallandub, kui te kombineerite `useTransition`-i `Suspense`-iga. `Suspense` võimaldab teie komponentidel enne renderdamist midagi "oodata", näiteks andmeid API-st.
Kui te käivitate andmete toomise `startTransition`-i sees, saab React aru, et te olete üleminekul uuele olekule, mis nõuab uusi andmeid. Selle asemel, et kohe näidata `Suspense` tagavaraväärtust (nagu suur laadimiskursor, mis nihutab lehe paigutust), ütleb `useTransition` Reactile, et ta jätkaks vana UI näitamist (oma isPending olekus), kuni uued andmed on kohale jõudnud ja uued komponendid on renderdamiseks valmis. See hoiab ära kiire andmetoomise korral järsud laadimise olekud ja loob palju sujuvama navigeerimiskogemuse.
`useDeferredValue`: Õe haak
Mõnikord ei kontrolli te koodi, mis käivitab olekuvärskenduse. Mis siis, kui te saate väärtuse vanemkomponendi rekvisiidina ja see väärtus muutub kiiresti, põhjustades teie komponendis aeglaseid uuesti renderdusi?
Siin on `useDeferredValue` kasulik. See on `useTransition`-i õe haak, mis saavutab sarnase tulemuse, aga erineva mehhanismi kaudu.
import { useState, useDeferredValue } from 'react';
function ProductList({ query }) {
// `deferredQuery` jääb renderdamise ajal `query` rekvisiidist "maha".
const deferredQuery = useDeferredValue(query);
// Loend renderdatakse uuesti edasilükatud väärtusega, mis on mitteblokeeriv.
const filteredProducts = useMemo(() => {
return allProducts.filter(p => p.name.includes(deferredQuery));
}, [deferredQuery]);
return <div>...</div>;
}
Peamine erinevus:
useTransitionmässib olekut määrava funktsiooni. Te kasutate seda, kui teie olete see, kes käivitab värskenduse.useDeferredValuemässib väärtuse, mis põhjustab aeglast renderdust. See tagastab selle väärtuse uue versiooni, mis "jääb maha" samaaegsete renderduste ajal, lükates uuesti renderdamise tegelikult edasi. Te kasutate seda, kui te ei kontrolli olekuvärskenduse ajastust.
Parimad tavad ja levinud lõkse
Millal `useTransition`-i kasutada
- CPU-intensiivsed renderdused: Peamine kasutusjuhtum. Suurte andmemassiivide filtreerimine, sortimine või teisendamine.
- Keerukad UI värskendused: Keerukate SVG-de, graafikute või diagrammide renderdamine, mida on kallis arvutada.
- Navigatsiooniüleminekute parandamine: Kui seda kasutatakse koos `Suspense`-iga, pakub see paremat kogemust lehtede või vaadete vahel navigeerimisel, mis nõuavad andmete toomist.
Millal `useTransition`-i MITTE kasutada
- Kiirete värskenduste jaoks: Ärge mässige iga olekuvärskendust üleminekusse. See lisab väikese koguse üldkulusid ja on kiirete renderduste korral ebavajalik.
- Värskenduste jaoks, mis nõuavad kohest tagasisidet: Nagu me nägime juhitava sisendi puhul, peaksid mõned värskendused olema kõrge prioriteediga. `useTransition`-i ülekasutamine võib muuta liidese lahtiühendatuks, kui kasutaja ei saa oodatud kohest tagasisidet.
- Koodi tükeldamise või memoeerimise asendajana: `useTransition` aitab hallata aeglaseid renderdusi, aga see ei muuda neid kiiremaks. Te peaksite ikka oma komponente optimeerima selliste tööriistadega nagu `React.memo`, `useMemo` ja koodi tükeldamine, kui see on asjakohane. `useTransition` on allesjäänud, vältimatu aegluse kasutajakogemuse haldamiseks.
Juurdepääsetavuse kaalutlused
Kui te kasutate `isPending` olekut laadimise tagasiside näitamiseks, on ülioluline sellest teavitada abistavate tehnoloogiate kasutajaid. Kasutage ARIA atribuute, et signaalida, et osa lehest on hõivatud uuendamisega.
<div
aria-busy={isPending}
style={{ opacity: isPending ? 0.5 : 1 }}
>
<ProductList products={filteredProducts} />
</div>
Te võite kasutada ka `aria-live` piirkonda, et teavitada, kui värskendus on lõpule viidud, tagades sujuva kogemuse kõigile kasutajatele üle maailma.
Järeldus: Sujuvate liideste ehitamine globaalsele vaatajaskonnale
Reacti `useTransition` haak on rohkem kui lihtsalt jõudluse optimeerimise tööriist; see on põhimõtteline nihe selles, kuidas me saame mõelda ja ehitada kasutajaliideseid. See annab meile võimaluse luua selge värskenduste hierarhia, tagades, et kasutaja otsesed interaktsioonid on alati prioriteediks, hoides rakenduse kogu aeg sujuva ja reageerivana.
Märkides mittekiireloomulised, rasked värskendused üleminekuteks, saame:
- Kõrvaldada blokeerivad renderdused, mis külmutavad UI.
- Hoida peamised juhtnupud, nagu tekstisisendid ja nupud, kohe reageerivana.
- Pakkuda selget visuaalset tagasisidet taustatoimingute kohta, kasutades
isPendingolekut. - Ehitada keerukaid, andmerikkaid rakendusi, mis tunduvad kasutajatele ĂĽle kogu maailma kerged ja kiired.
Kuna rakendused muutuvad keerukamaks ja kasutaja ootused jõudlusele kasvavad jätkuvalt, ei ole selliste samaaegsete funktsioonide nagu `useTransition` valdamine enam luksus – see on vajalik igale arendajale, kes suhtub tõsiselt erakordsete kasutajakogemuste loomisesse. Alustage selle integreerimist oma projektidesse juba täna ja andke oma kasutajatele kiire, mitteblokeeriv liides, mida nad väärivad.